//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <core.h>
#include <_hal.h>
#include <sysnum.h>
#include <init.h>
#include "common.h"
#include "scgate.h"

DECL_ASMLINKAGE void SystemCallHandler();

EXTERN DECL_CODEINIT void CDECL InitSystemCall()
{
    InitSystemCallTable();
    SetSystemGate(SystemCallVector, (virtaddr_t)&SystemCallHandler);
}

EXTERN void __SystemCallHandler()
{
DECL_ASMENTRY(SystemCallHandler)

    ASM("push   %eax;");            // push InterruptContext::u.uSystemCallNo

    __SAVE_SOFTWARE_REGS();

    __SETUP_KERNEL_REGS();

    ASM("cmpl   %0, %%eax;"
        "jb     __SystemCallHandler_Next;"
        : :"i"(c_uNumOfSystemCall));

    ASM("movl   %0, 24(%%esp);"         // move E_INVALID_ARGUMENT to
        "jmp    _ReturnFromSystemCall;" // InterruptContext::eax, and return
        : :"i"(E_INVALID_ARGUMENT));

    ASM("__SystemCallHandler_Next:"
        "call   *_g_fnSystemCalls(, %eax, 4);");

    ASM("movl   %eax, 24(%esp);");      // save eax to InterruptContext::eax

DECL_ASMENTRY(ReturnFromSystemCall)

    ASM("jmp    _ReturnFromInterrupt;");

DECL_ASMENTRY(ThreadStartup)

    Sti();

    TIMEPEG_SCHEDULE_STOP

    EnablePreemption();

    ASM("movl   $0, %ebp;");

    ASM("popl   %%eax;"
        "call   *%%eax;"
        "addl   $4, %%esp;"
        "jmp    _ReturnFromSystemCall;"
        : : :"eax");

DECL_ASMENTRY(SystemThreadStartup)

    Sti();

    TIMEPEG_SCHEDULE_STOP

    EnablePreemption();

    ASM("movl   $0, %ebp;");

    ASM("popl   %%eax;"
        "call   *%%eax;"
        : : :"eax");

    assert0();
}
